
package com.ansion.utils.file;

import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.os.storage.StorageManager;

import com.ansion.utils.ResourceUtils;

import java.io.File;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import java.util.UUID;

public class StorageUtils {

    private static final String ANDROID_DATA = "Android/data/";
    private static final String ANDROID_MEDIA = "Android/media/";
    private static final String ANDROID_OBB = "Android/obb/";
    public static final String MOVIES_BOTIM = "Movies/BOTIM";
    public static final String PICTURES_BOTIM = "Pictures/BOTIM";

    public static boolean isSDCardWriteable() {
        String state = Environment.getExternalStorageState();
        if (!Environment.MEDIA_MOUNTED.equals(state))
            return false;
        if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state))
            return false;
        return true;
    }

    /**
     * get external storage available size which can be written.
     *
     * @return
     */
    public static long getSDCardWriteAvailableSize() {
        String status = Environment.getExternalStorageState();
        if (status.equals(Environment.MEDIA_MOUNTED)) {
            try {
                File path = Environment.getExternalStorageDirectory();
                StatFs stat = new StatFs(path.getPath());
                long blockSize = stat.getBlockSizeLong();
                long availableBlocks = stat.getAvailableBlocksLong();
                return availableBlocks * blockSize;
            } catch (IllegalArgumentException e) {
                status = Environment.MEDIA_REMOVED;
            }
        }
        return -1;
    }

    /**
     * get data directory storage available size which can be written.
     *
     * @return
     */
    public static long getDataWriteAvailableSize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long availableBlocks = stat.getAvailableBlocksLong();
        return availableBlocks * blockSize;
    }

    public static long directorySize(String rootPath) {
        return directorySize(new File(rootPath));
    }

    public static long directorySize(File rootPath) {
        if (rootPath == null || !rootPath.exists()) {
            return 0;
        }

        if (rootPath.isFile()) {
            return rootPath.length();
        } else if (rootPath.isDirectory()) {
            long sizeTotal = 0;

            File[] subItems = rootPath.listFiles();
            for (File file : subItems) {
                sizeTotal += directorySize(file);
            }

            return sizeTotal;
        }

        return 0;
    }

    public static boolean deleteDirectory(File rootPath, boolean fileOnly) {
        if (rootPath == null || !rootPath.exists()) {
            return false;
        }

        if (rootPath.isFile()) {
            return rootPath.delete();
        } else if (rootPath.isDirectory()) {
            boolean deleteFailed = false;

            File[] subItems = rootPath.listFiles();
            for (File file : subItems) {
                deleteFailed = deleteFailed || !deleteDirectory(file, fileOnly);
            }

            if (!fileOnly) {
                rootPath.delete();
            }

            return !deleteFailed;
        }

        return true;
    }

    /**
     * get app storage size
     * @param context
     * @return
     */
    public static long getAppStorageSize(Context context) {
        try {
            PackageManager pm = context.getPackageManager();
            ApplicationInfo applicationInfo = pm.getApplicationInfo(context.getPackageName(), 0);

            long totalSize = 0;

            // 1. APK文件大小
            if (applicationInfo.sourceDir != null) {
                File apkFile = new File(applicationInfo.sourceDir);
                totalSize += apkFile.length();
            }

            // 2. lib文件大小
            if (applicationInfo.nativeLibraryDir != null) {
                File nativeLibraryFile = new File(applicationInfo.nativeLibraryDir);
                totalSize += getFolderSize(nativeLibraryFile);
            }

            // 3. Split APK大小（如果有的话）
            if (applicationInfo.splitSourceDirs != null) {
                for (String splitPath : applicationInfo.splitSourceDirs) {
                    File splitFile = new File(splitPath);
                    totalSize += splitFile.length();
                }
            }

            // 4. 内部存储数据大小 - 只计算data目录，因为cache和codeCache都在data目录下
            File dataDir = new File(applicationInfo.dataDir);
            totalSize += getFolderSize(dataDir);

            // 5. 外部存储数据大小（如果有权限）
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                // 只计算Android/data下的应用目录，因为其他目录都是其子目录
                File androidDataDir = new File(Environment.getExternalStorageDirectory(),
                        ANDROID_DATA + context.getPackageName());
                totalSize += getFolderSize(androidDataDir);

                File androidMediaDir = new File(Environment.getExternalStorageDirectory(),
                        ANDROID_MEDIA + context.getPackageName());
                totalSize += getFolderSize(androidDataDir);

                File androidObbDir = new File(Environment.getExternalStorageDirectory(),
                        ANDROID_OBB + context.getPackageName());
                totalSize += getFolderSize(androidObbDir);

                File moviesDir = new File(Environment.getExternalStorageDirectory(),
                        MOVIES_BOTIM);
                totalSize += getFolderSize(moviesDir);

                File picturesDir = new File(Environment.getExternalStorageDirectory(),
                        PICTURES_BOTIM);
                totalSize += getFolderSize(picturesDir);
            }

            return totalSize;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * available storage size
     * @return
     */
    public static long getAvailableStorageSize() {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                StorageStatsManager storageStatsManager = (StorageStatsManager)
                        ResourceUtils.getContext().getSystemService(Context.STORAGE_STATS_SERVICE);

                if (storageStatsManager != null) {
                    UUID defaultStorageUuid = StorageManager.UUID_DEFAULT;
                    return storageStatsManager.getFreeBytes(defaultStorageUuid);
                }
            }

            // 备选方法
            File path = Environment.getDataDirectory();
            StatFs stat = new StatFs(path.getPath());
            return stat.getAvailableBytes();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * used storage size
     * @return
     */
    public static long getUsedStorageSize() {
        long totalSize = getTotalStorageSize();
        long availableSize = getAvailableStorageSize();
        return totalSize - availableSize;
    }

    /**
     * total storage size
     * @return
     */
    public static long getTotalStorageSize() {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // Android 8.0及以上使用StorageStatsManager
                StorageStatsManager storageStatsManager = (StorageStatsManager)
                        ResourceUtils.getContext().getSystemService(Context.STORAGE_STATS_SERVICE);

                if (storageStatsManager != null) {
                    // 获取默认存储的UUID
                    UUID defaultStorageUuid = StorageManager.UUID_DEFAULT;
                    return storageStatsManager.getTotalBytes(defaultStorageUuid);
                }
            }
            // 如果上述方法都失败，使用传统方法
            File path = Environment.getDataDirectory();
            StatFs stat = new StatFs(path.getPath());
            return stat.getTotalBytes();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    // 递归计算文件夹大小
    private static long getFolderSize(File directory) {
        long length = 0;
        if (directory == null || !directory.exists()) return 0;
        File[] files = directory.listFiles();
        if (files == null) return 0;

        for (File file : files) {
            if (file.isFile()) {
                length += file.length();
            } else {
                length += getFolderSize(file);
            }
        }
        return length;
    }

    /**
     * Divide by 1000 to get KB
     *
     * @param bytes
     * @return
     */
    public static String fomatString(long bytes) {
        DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
        DecimalFormat decimalFormat = new DecimalFormat("0", symbols);
        return decimalFormat.format(bytes / 1000);
    }

}
